/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2006
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.analysisModel;

import java.io.Serializable;
import java.util.ArrayList;

import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;
import br.ufmg.dees.insane.util.geometricProperties.GeometricProperties;

/**
*A class representing a line analysis model of a ParametricElement.
*
*@author Lucas, Marcelo & Pitangueira, Roque & Fonseca, Flavio
*@version 1.0
*@since September 2004, modified October 2006
*/
public abstract class Line implements Serializable, AnalysisModel {
	
	private static final long serialVersionUID = 1L;
	
	/** Constructs a Line analysis model*/
	public Line()
	{
	}
	
	/**
	 * Returns the number of degrees of freedom for this analysis model.
	 * @return The number of degrees of freedom for this analysis model.
	 */
	protected abstract int getNdf();
	
	/** Return the normal vector according this analysis model.
	*@param a The IMatrix of local derivates.
	*@param b The IMatrix of nodal coordinates.
	*@return The normal vector according this analysis model.
	*/
	protected abstract IVector getNormalVector(IMatrix a, IMatrix b);
	
	/* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c) {
    	IMatrix invertJacobian;
		IMatrix dG = new IMatrix(1,d.getNumCol());
		IMatrix b = new IMatrix(1,(this.getNdf()*dG.getNumCol()));
		IMatrix normal = new IMatrix(1,this.getNdf());
		IVector aux = new IVector(dG.getNumCol());
		
		dG.setZero();
		b.setZero();
		normal.setZero();
		aux.zero();
		
		invertJacobian = this.invertJacobian(this.getJacobian(d, c));
		dG.mul(invertJacobian, d);
		dG.getRow(0,aux);
		normal.setRow(0,this.getNormalVector(d, c));
		b.mul(normal, this.getStateVariableOperator(null, aux, null));
		
		return(b);
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getDualInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getDualInternalVariableOperator(IMatrix e) {
    	IMatrix d = new IMatrix(1,1);
		d.setZero();
		d.setElement(0, 0, e.getElement(0, 0));
		
		return d;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getStateVariableOperator(br.ufmg.dees.insane.util.IVector)
     */
    public IMatrix getStateVariableOperator(IMatrix d, IVector n, IMatrix c) {
    	IMatrix matrixN = new IMatrix(this.getNdf(),(this.getNdf()*n.getSize()));
		matrixN.setZero();
		
		for(int i = 0; i < (n.getSize()); i++)
		{
			for(int j = 0; j < (this.getNdf()); j++)
			{
				matrixN.setElement(j, (((this.getNdf())*i)+j), (n.getElement(i)));
			}
		}
		return matrixN;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getNumberOfDualInternalVariables()
     */
    public int getNumberOfDualInternalVariables()
	{
		return 1;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getNumberOfInternalVariables()
     */
    public int getNumberOfInternalVariables()
	{
		return 1;
	}
	
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getDualInternalVariablesDirLabels()
     */
    public String[] getDualInternalVariablesLabels() {
        String[] Dlabels = {"sigmaXX"};
        return Dlabels;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariablesDirLabels()
     */
    public String[] getInternalVariablesLabels() {
        String[] Dlabels = {"epsilonXX"};
        return Dlabels;
    }
    
	/* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getJacobianTransformation(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IMatrix)
     */
	public double getJacobianTransformation(IMatrix dl, IMatrix cN)
	{
		IVector n_Xi = new IVector(dl.getNumCol());
		IMatrix aux = new IMatrix(this.getNdf(),1);
		IMatrix jacobian = new IMatrix(1,1);
		double j1 = 0;
		double j2 = 0;
		double j3 = 0;
		
		n_Xi.zero();
		aux.setZero();
		jacobian.setZero();
		
		IVector normalVector = this.getNormalVector(dl,cN);
		dl.getRow(0,n_Xi);
		aux.mul((this.getStateVariableOperator(null, n_Xi, null)),cN);
		
		j1 = (normalVector.getElement(0)*aux.getElement(0,0));
		if(this instanceof Line_2D || this instanceof Line_3D)
			j2 = (normalVector.getElement(1)*aux.getElement(1,0));
		if(this instanceof Line_3D)
			j3 = (normalVector.getElement(2)*aux.getElement(2,0));
		
		jacobian.setElement(0,0,(j1+j2+j3));
		
		return(jacobian.determinantLU());
	}
	
	/** Return the jacobian matrix.
	*@param dl The matrix of local derivates.
	*@param cN The matrix of nodal coordinates.
	*@return dl * cN The jacobian matrix.
	*/
	public IMatrix getJacobian(IMatrix dl, IMatrix cN)
	{
		IVector n_Xi = new IVector(dl.getNumCol());
		IMatrix aux = new IMatrix(this.getNdf(),1);
		IMatrix jacobian = new IMatrix(1,1);
		double j1 = 0;
		double j2 = 0;
		double j3 = 0;
		
		n_Xi.zero();
		aux.setZero();
		jacobian.setZero();
		
		IVector normalVector = this.getNormalVector(dl,cN);
		dl.getRow(0,n_Xi);
		aux.mul((this.getStateVariableOperator(null, n_Xi, null)),cN);
		
		j1 = (normalVector.getElement(0)*aux.getElement(0,0));
		//if(this.getValidEquation(1))
			j2 = (normalVector.getElement(1)*aux.getElement(1,0));
		//if(this.getValidEquation(2))
			j3 = (normalVector.getElement(2)*aux.getElement(2,0));
		
		jacobian.setElement(0,0,(j1+j2+j3));
		
		return(jacobian);
	}
	
	/** Return the inverse of jacobian matrix.
	*@param a The jacobian matrix.
	*@return the inverse of jacobian matrix.
	*/
	protected IMatrix invertJacobian(IMatrix a)
	{
		double inv = 1/(a.getElement(0,0));
		IMatrix b = new IMatrix(1,1);
		b.setZero();
		b.setElement(0,0,inv);
		
		return (b);
	}

	public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c, IMatrix u) {
		// TODO Auto-generated method stub
		return null;
	}

	public IMatrix modifyInternalVariableOperator(IMatrix e, IMatrix p) {
		// TODO Auto-generated method stub
		return null;
	}

	public IMatrix modifyDualInternalVariableOperator(IMatrix e, GeometricProperties gps) {
		// TODO Auto-generated method stub
		return null;
	}
	
	public IVector modifyDualInternalVariableVector(IVector s, GeometricProperties gps) {
		// TODO Auto-generated method stub
		return null;
	}

	public IMatrix getGeometricOperator(IVector n1) {
		// TODO Auto-generated method stub
		return null;
	}

	public IVector getInternalVariablesVector(IVector a, IMatrix b) {
		// TODO Auto-generated method stub
		return null;
	}

	public IVector getDualInternalVariablesVector(IVector a, IMatrix b) {
		// TODO Auto-generated method stub
		return null;
	}

	public IMatrix getInternalVariablesTensor(IVector a, IMatrix b) {
		// TODO Auto-generated method stub
		return null;
	}

	public IMatrix getDualInternalVariablesTensor(IVector a, IMatrix b) {
		// TODO Auto-generated method stub
		return null;
	}

	public IVector expandVector(IVector a) {
		// TODO Auto-generated method stub
		return null;
	}

	public IMatrix expandTensor(IVector a) {
		// TODO Auto-generated method stub
		return null;
	}

	public IVector reduceVector(IVector a) {
		// TODO Auto-generated method stub
		return null;
	}

	public IVector reduceTensor(IMatrix a) {
		// TODO Auto-generated method stub
		return null;
	}

	public int getDominion() {
		// TODO Auto-generated method stub
		return 0;
	}

	public double getIntegrationFactor(IVector n, IMatrix cN, GeometricProperties gps) {
		// TODO Auto-generated method stub
		return 0;
	}

	public IMatrix getTransformationMatrix(IMatrix dl, IMatrix cN) {
		// TODO Auto-generated method stub
		return null;
	}

	public double getJ2(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

	public IVector getdJ2dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

	public double getJ3(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

	public IVector getdJ3dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

	public double getI1(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

	public IVector getdI1dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

	public double getI2(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

	public IVector getdI2dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

	public double getI3(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

	public IVector getdI3dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

	public ArrayList getDOFLabels(int n) {
		// TODO Auto-generated method stub
		return null;
	}

}
